﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Data;

namespace Utilities
{
    public class XML
    {

        protected XmlDocument xmlDocument;
        public string strXmlFilePath;
        public string strMasterNode;
        public string strHeaderNode;
        public string strLine1Node;
        public string strLine2Node;
        public string strLine3Node;

        public XML()
        {
            xmlDocument = new XmlDocument();
        }

        public XML(string strXmlFilePathConstructor)
        {
            xmlDocument = new XmlDocument();
            this.strXmlFilePath = strXmlFilePathConstructor;
            xmlDocument.Load(this.strXmlFilePath);
        }

        public void setXmlFilePath(string strFilePath)
        {
            this.strXmlFilePath = strFilePath;
            xmlDocument.Load(this.strXmlFilePath);
        }

        public void setMasterNode(string strMasterNodeKey)
        {
            this.strMasterNode = strMasterNodeKey;
        }

        public void setHeaderNode(string strHeaderNodeKey)
        {
            this.strHeaderNode = strHeaderNodeKey;
        }

        public void setLine1Node(string strLine1NodeKey)
        {
            this.strLine1Node = strLine1NodeKey;
        }

        public void setLine2Node(string strLine2NodeKey)
        {
            this.strLine2Node = strLine2NodeKey;
        }

        public void setLine3Node(string strLine3NodeKey)
        {
            this.strLine3Node = strLine3NodeKey;
        }

        private void saveXML()
        {
            xmlDocument.Save(this.strXmlFilePath);
        }

        public void saveSelectedSingleNode(XmlElement xmlElement, string strKey, string strValue)
        {
            xmlElement.SetAttribute(strKey, strValue);
            saveXML();
        }

        public void saveSelectedSingleNodeByXPathExpression(string strXPathExpression, string strKey, string strValue)
        {
            XmlElement xmlElement = (XmlElement)xmlDocument.SelectSingleNode(strXPathExpression);
            xmlElement.SetAttribute(strKey, strValue);
            saveXML();
        }

    }

    public class XMLBuilder : XML
    {
        public string buildMasterXPathExpression(string strKeyControl, string strValueControl)
        {
            return "//" + this.strMasterNode + "[@" + strKeyControl + "='" + strValueControl + "']";
        }

        public string buildHeaderXPathExpression(string strKeyControl, string strValueControl)
        {
            return "//" + this.strMasterNode + "/" + this.strHeaderNode +
                   "[@" + strKeyControl + "='" + strValueControl + "']";
        }

        public string buildLine1XPathExpression(string strKeyControl, string strValueControl)
        {
            return "//" + this.strMasterNode + "/" + this.strHeaderNode +
                   "/" + this.strLine1Node + "[@" + strKeyControl + "='" + strValueControl + "']";
        }

        public string buildLine2XPathExpression(string strKeyControl, string strValueControl)
        {
            return "//" + this.strMasterNode + "/" + this.strHeaderNode +
                   "/" + this.strLine1Node + "/" + this.strLine2Node +
                   "[@" + strKeyControl + "='" + strValueControl + "']";
        }

        public string buildLine3XPathExpression(string strKeyControl, string strValueControl)
        {
            return "//" + this.strMasterNode + "/" + this.strHeaderNode +
                   "/" + this.strLine1Node + "/" + this.strLine2Node +
                   "/" + this.strLine3Node + "[@" + strKeyControl + "='" + strValueControl + "']";
        }

        public XmlElement buildMasterXmlElement()
        {
            string xPathExpression = "//" + this.strMasterNode;
            XmlElement xmlElement = (XmlElement)xmlDocument.SelectSingleNode(xPathExpression);
            return xmlElement;
        }

        public XmlElement buildHeaderXmlElement()
        {
            XmlElement xmlElement;
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            if (xmlElements.Count == 1)
            {
                XmlNode xmlNode = xmlElements.Item(0);
                xmlElement = (XmlElement)xmlNode;
                return xmlElement;
            }
            else return null;
        }

        public XmlNodeList buildHeaderXmlElements()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            return xmlElements;
        }

        public XmlElement buildLine1XmlElement()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode +
                                     "/" + this.strLine1Node;
            XmlElement xmlElement;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            if (xmlElements.Count == 1)
            {
                XmlNode xmlNode = xmlElements.Item(0);
                xmlElement = (XmlElement)xmlNode;
                return xmlElement;
            }
            else return null;
        }

        public XmlNodeList buildLine1XmlElements()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode +
                                     "/" + this.strLine1Node;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            return xmlElements;
        }

        public XmlElement buildLine2XmlElement()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode +
                                     "/" + this.strLine1Node + "/" + this.strLine2Node;
            XmlElement xmlElement;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            if (xmlElements.Count == 1)
            {
                XmlNode xmlNode = xmlElements.Item(0);
                xmlElement = (XmlElement)xmlNode;
                return xmlElement;
            }
            else return null;
        }

        public XmlNodeList buildLine2XmlElements()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode +
                                     "/" + this.strLine1Node + "/" + this.strLine2Node;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            return xmlElements;
        }

        public XmlElement buildLine3XmlElement()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode +
                                     "/" + this.strLine1Node + "/" + this.strLine2Node +
                                     "/" + this.strLine3Node;
            XmlElement xmlElement;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            if (xmlElements.Count == 1)
            {
                XmlNode xmlNode = xmlElements.Item(0);
                xmlElement = (XmlElement)xmlNode;
                return xmlElement;
            }
            else return null;
        }

        public XmlNodeList buildLine3XmlElements()
        {
            string xPathExpression = "//" + this.strMasterNode + "/" + this.strHeaderNode +
                                     "/" + this.strLine1Node + "/" + this.strLine2Node +
                                     "/" + this.strLine3Node;
            XmlNodeList xmlElements = (XmlNodeList)xmlDocument.SelectNodes(xPathExpression);
            return xmlElements;
        }
    }

    public class XMLSetter : XMLBuilder
    {

        public void setMasterNodeValue(string strKeyControl, string strValueControl, string strKeySet, string strValueSet)
        {
            try
            {
                saveSelectedSingleNodeByXPathExpression(buildMasterXPathExpression(strKeyControl, strValueControl), strKeySet, strValueSet);
            }
            catch (Exception ex)
            {
                string str = ex.ToString();
                Utilities.GlobalObject.LOGGER.log(str);
            }
        }

        public void setHeaderNodeValue(string strKeyControl, string strValueControl, string strKeySet, string strValueSet)
        {
            try
            {
                saveSelectedSingleNodeByXPathExpression(buildHeaderXPathExpression(strKeyControl, strValueControl), strKeySet, strValueSet);
            }
            catch (Exception ex)
            {
                string str = ex.ToString();
                GlobalObject.LOGGER.log(str);
            }
        }

        public void setLine1NodeValue(string strKeyControl, string strValueControl, string strKeySet, string strValueSet)
        {
            try
            {
                saveSelectedSingleNodeByXPathExpression(buildLine1XPathExpression(strKeyControl, strValueControl), strKeySet, strValueSet);
            }
            catch (Exception ex)
            {
                string str = ex.ToString();
                GlobalObject.LOGGER.log(str);
            }
        }

        public void setLine2NodeValue(string strKeyControl, string strValueControl, string strKeySet, string strValueSet)
        {
            try
            {
                saveSelectedSingleNodeByXPathExpression(buildLine2XPathExpression(strKeyControl, strValueControl), strKeySet, strValueSet);
            }
            catch (Exception ex)
            {
                string str = ex.ToString();
                GlobalObject.LOGGER.log(str);
            }
        }

        public void setLine3NodeValue(string strKeyControl, string strValueControl, string strKeySet, string strValueSet)
        {
            try
            {
                saveSelectedSingleNodeByXPathExpression(buildLine3XPathExpression(strKeyControl, strValueControl), strKeySet, strValueSet);
            }
            catch (Exception ex)
            {
                string str = ex.ToString();
                GlobalObject.LOGGER.log(str);
            }
        }
    }

    public class XMLGetter : XMLBuilder
    {
        public string getMasterNodeValue(string strKey)
        {
            string strValue = buildMasterXmlElement().GetAttribute(strKey);
            return strValue;
        }

        public string getHeaderNodeValue(string strKey)
        {
            string strValue = null;
            XmlElement xmlElement = buildHeaderXmlElement();
            if (xmlElement != null)
            {
                strValue = xmlElement.GetAttribute(strKey);
            }
            return strValue;
        }

        public DataTable getHeaderNodeValues()
        {
            XmlNodeList xmlElements = buildHeaderXmlElements();

            //Build DataTable
            //Using one of the xmlElement to count number of attributes then build accordingly number of columns.
            XmlNode xmlNode = xmlElements.Item(0);
            XmlElement firstXmlElement = (XmlElement)xmlNode;
            XmlAttributeCollection xmlAttributeColl = firstXmlElement.Attributes;
            DataTable dtTarget = new DataTable();
            for (int i = 1; i <= xmlAttributeColl.Count; i++)
            {
                dtTarget.Columns.Add(new DataColumn("Attribute" + i.ToString(), typeof(string)));
            }

            //Extract data from xmlElements
            foreach (XmlElement xmlElement in xmlElements)
            {
                DataRow drowDt = dtTarget.NewRow();
                //Get all attribute in a xmlElement
                xmlAttributeColl = xmlElement.Attributes;
                //Loop over one by one attribute
                for (int i = 0; i < xmlAttributeColl.Count; i++)
                {
                    //Get the value return from xmlElement.attribute
                    string strTemp = xmlElement.GetAttribute(xmlAttributeColl[i].Name);
                    drowDt[i] = strTemp;
                }
                dtTarget.Rows.Add(drowDt);
            }

            //Return the datatable
            return dtTarget;
        }

        public string getLine1NodeValue(string strKey)
        {
            string strValue = null;
            XmlElement xmlElement = buildLine1XmlElement();
            if (xmlElement != null)
            {
                strValue = xmlElement.GetAttribute(strKey);
            }
            return strValue;
        }

        public DataTable getLine1NodeValues()
        {
            XmlNodeList xmlElements = buildLine1XmlElements();

            //Build DataTable
            //Using one of the xmlElement to count number of attributes then build accordingly number of columns.
            XmlNode xmlNode = xmlElements.Item(0);
            XmlElement firstXmlElement = (XmlElement)xmlNode;
            XmlAttributeCollection xmlAttributeColl = firstXmlElement.Attributes;
            DataTable dtTarget = new DataTable();
            for (int i = 1; i <= xmlAttributeColl.Count; i++)
            {
                dtTarget.Columns.Add(new DataColumn("Attribute" + i.ToString(), typeof(string)));
            }

            //Extract data from xmlElements
            foreach (XmlElement xmlElement in xmlElements)
            {
                DataRow drowDt = dtTarget.NewRow();
                //Get all attribute in a xmlElement
                xmlAttributeColl = xmlElement.Attributes;
                //Loop over one by one attribute
                for (int i = 0; i < xmlAttributeColl.Count; i++)
                {
                    //Get the value return from xmlElement.attribute
                    string strTemp = xmlElement.GetAttribute(xmlAttributeColl[i].Name);
                    drowDt[i] = strTemp;
                }
                dtTarget.Rows.Add(drowDt);
            }

            //Return the datatable
            return dtTarget;
        }

        public string getLine2NodeValue(string strKey)
        {
            string strValue = null;
            XmlElement xmlElement = buildLine2XmlElement();
            if (xmlElement != null)
            {
                strValue = xmlElement.GetAttribute(strKey);
            }
            return strValue;
        }

        public DataTable getLine2NodeValues()
        {
            XmlNodeList xmlElements = buildLine2XmlElements();

            //Build DataTable
            //Using one of the xmlElement to count number of attributes then build accordingly number of columns.
            XmlNode xmlNode = xmlElements.Item(0);
            XmlElement firstXmlElement = (XmlElement)xmlNode;
            XmlAttributeCollection xmlAttributeColl = firstXmlElement.Attributes;
            DataTable dtTarget = new DataTable();
            for (int i = 1; i <= xmlAttributeColl.Count; i++)
            {
                dtTarget.Columns.Add(new DataColumn("Attribute" + i.ToString(), typeof(string)));
            }

            //Extract data from xmlElements
            foreach (XmlElement xmlElement in xmlElements)
            {
                DataRow drowDt = dtTarget.NewRow();
                //Get all attribute in a xmlElement
                xmlAttributeColl = xmlElement.Attributes;

                //Loop over one by one attribute
                for (int i = 0; i < xmlAttributeColl.Count; i++)
                {
                    string strNameOfAttribute = xmlAttributeColl[i].Name;
                    //string strValueOfAttribute = xmlAttributeColl[0].Value;
                    //Get the value return from xmlElement.attribute
                    string strTemp = xmlElement.GetAttribute(strNameOfAttribute);
                    drowDt[i] = strTemp.Trim();
                }
                dtTarget.Rows.Add(drowDt);
            }

            //Return the datatable
            return dtTarget;
        }

        public string getLine3NodeValue(string strKey)
        {
            string strValue = null;
            XmlElement xmlElement = buildLine3XmlElement();
            if (xmlElement != null)
            {
                strValue = xmlElement.GetAttribute(strKey);
            }
            return strValue;
        }

        public DataTable getLine3NodeValues()
        {
            XmlNodeList xmlElements = buildLine3XmlElements();

            //Build DataTable
            //Using one of the xmlElement to count number of attributes then build accordingly number of columns.
            XmlNode xmlNode = xmlElements.Item(0);
            XmlElement firstXmlElement = (XmlElement)xmlNode;
            XmlAttributeCollection xmlAttributeColl = firstXmlElement.Attributes;
            DataTable dtTarget = new DataTable();
            for (int i = 1; i <= xmlAttributeColl.Count; i++)
            {
                dtTarget.Columns.Add(new DataColumn("Attribute" + i.ToString(), typeof(string)));
            }

            //Extract data from xmlElements
            foreach (XmlElement xmlElement in xmlElements)
            {
                DataRow drowDt = dtTarget.NewRow();
                //Get all attribute in a xmlElement
                xmlAttributeColl = xmlElement.Attributes;
                //Loop over one by one attribute
                for (int i = 0; i < xmlAttributeColl.Count; i++)
                {
                    //Get the value return from xmlElement.attribute
                    string strTemp = xmlElement.GetAttribute(xmlAttributeColl[i].Name);
                    drowDt[i] = strTemp;
                }
                dtTarget.Rows.Add(drowDt);
            }

            //Return the datatable
            return dtTarget;
        }

    }
}
